/*---------------------------------------
/ Test Program for System Calls
/ Added in Project2
/
/ This Test is to test the syscalls about
/	Locks and Conditions
/ eg.
/	CreateLock,	......
/	CreateCondition,	......
/
/ by OceanMaster
/---------------------------------------*/

#include "syscall.h"

int i;
int Lock[4];
int Condition[4];


/*Test Case 1*/
void test1_thread1()
{
	WriteFormat("t1t2: Test1_thread2 is trying to Acquire Lock %d \n",51,Lock+2,1);
	AcquireLock(Lock[2]);
	WriteFormat("t1t2: Test2_thread2 Acquired Lock %d \n",39,Lock+2,1);
	ReleaseLock(Lock[2]);
	WriteFormat("t1t2: Test2_thread2 Released Lock %d \n",39,Lock+2,1);
	Exit(0);
}

void test1_main()
{
	WriteFormat("----------Test Case I----------\n",33,0,0);
	WriteFormat("/*Test Function of Lock      */\n",33,0,0);
	
	WriteFormat("1-1 CreateLock                 \n",33,0,0);
	Lock[0] = CreateLock("TestLock1",9);
	WriteFormat("    Lock Created, handle is %d \n",33,Lock,1);
	
	WriteFormat("1-2 AcquireLock                \n",33,0,0);
	AcquireLock(Lock[0]);
	WriteFormat("    Lock Acquired, handle is %d\n",33,Lock,1);
	
	WriteFormat("1-3 ReleaseLock                \n",33,0,0);
	ReleaseLock(Lock[0]);
	WriteFormat("    Lock Released, handle is %d\n",33,Lock,1);
	
	WriteFormat("1-4 DestroyLock                \n",33,0,0);
	DestroyLock(Lock[0]);
	WriteFormat("    Lock %d Destroyed          \n",33,Lock,1);
	WriteFormat("    Trying to Destroy Lock %d Again \n",38,Lock,1);
	DestroyLock(Lock[0]);
	WriteFormat("    Destory Lock %d should FAIL because this Lock is already deleted \n",71,Lock,1);
	
	WriteFormat("1-5 Confirm Lock %d Destroyed  \n",33,Lock,1);
	WriteFormat("    Trying to Acquire Lock %d  \n",33,Lock,1);
	AcquireLock(Lock[0]);
	WriteFormat("    Acquire Lock %d should FAIL because this Lock is already deleted \n",71,Lock,1);
	
	WriteFormat("1-6 Lock Function in Multi Thread \n",36,0,0);
	WriteFormat("    Create New Lock \n",22,0,0);
	Lock[2] = CreateLock("MultiThreadTestLock1",20);
	WriteFormat("    Acquire New Lock %d \n",26,Lock+2,1);
	AcquireLock(Lock[2]);
	WriteFormat("    Fork another thread to Acquire this Lock \n",47,0,0);
	Fork(test1_thread1);
	WriteFormat("    Yield to test1_thread1\n",28,0,0);
	Yield();
	WriteFormat("    Release Lock %d and Again Yield to test1_thread1\n",54,Lock+2,1);
	ReleaseLock(Lock[2]);
	Yield();
	AcquireLock(Lock[2]);
	WriteFormat("    Re-Acquired Lock %d \n",26,Lock+2,1);
	
	ReleaseLock(Lock[2]);
	DestroyLock(Lock[2]);
	WriteFormat("------------test end-----------\n",33,0,0);
	return;
}


/*Test Case 2*/
void test2_thread1()
{
	WriteFormat("t2t1: Test2_thread1 is ready, waiting for main thread to Sleep\n",64,0,0);
	AcquireLock(Lock[0]);
	
	WriteFormat("t2t1: Main thread has been sleeping, Signal Condition %d to Wake Him Up\n",73,Condition,1);
	SignalCondition(Condition[0],Lock[0]);

	ReleaseLock(Lock[0]);
	Exit(0);
}

void test2_thread2()
{
	WriteFormat("t2t2: Test2_thread2 is ready to wait on Condition %d \n",55,Condition,1);
	AcquireLock(Lock[0]);
	WaitCondition(Condition[0],Lock[0]);
	WriteFormat("t2t2: Test2_thread2 is wake up from Condition %d \n",51,Condition,1);
	ReleaseLock(Lock[0]);
	Exit(0);
}

void test2_main()
{
	WriteFormat("----------Test Case II---------\n",33,0,0);
	WriteFormat("/*Test Function of Condition */\n",33,0,0);
	
	WriteFormat("2-0 Prepare Lock to be used    \n",33,0,0);
	Lock[0] = CreateLock("TestConditionLock1",18);
	WriteFormat("    Lock Created, handle is %d \n",38,Lock,1);
	
	WriteFormat("2-1 CreateCondition            \n",33,0,0);
	Condition[0] = CreateCondition("TestCondition1",14);
	WriteFormat("    Condition Created, handle is %d \n",38,Lock,1);
	
	WriteFormat("2-2 Wait and Signal Condition  \n",33,0,0);
	AcquireLock(Lock[0]);
	WriteFormat("    Lock Acquired, handle is %d\n",33,Lock,1);
	Fork(test2_thread1);
	WriteFormat("    Forked another thread to Signal Me Up later \n",50,0,0);
	Yield();
	WriteFormat("    Main thread is waiting!!   \n",33,0,0);
	WaitCondition(Condition[0],Lock[0]);
	WriteFormat("    Main thread is Waken Up by test2_thread1\n",46,0,0);
	ReleaseLock(Lock[0]);
	
	WriteFormat("2-3 Broadcast Condition        \n",33,0,0);
	WriteFormat("    Fork 5 threads to wait in Condition %d \n",45,Condition,1);
	for(i=0;i<5;i++)
	{
		Fork(test2_thread2);
		Yield();
	}
	WriteFormat("    Main thread now broadcast Condition %d \n",45,Condition,1);
	AcquireLock(Lock[0]);
	BroadcastCondition(Condition[0],Lock[0]);
	ReleaseLock(Lock[0]);
	
	WriteFormat("    Main thread now release Lock %d and wait some time to let thread2 run\n",75,Lock,1);
	for(i=0;i<5;i++)
		Yield();
	AcquireLock(Lock[0]);

	WriteFormat("2-4 Destroy Condition          \n",33,0,0);
	DestroyCondition(Condition[0]);
	WriteFormat("    Condition %d Destroyed     \n",33,Condition,1);
	
	WriteFormat("2-5 Confirm Condition %d Destroyed\n",36,Condition,1);
	WriteFormat("    Trying to Wait Condition %d \n",34,Condition,1);
	SignalCondition(Condition[0],Lock[0]);
	WriteFormat("    Wait Condition %d should FAIL because this Lock is already deleted \n",73,Condition,1);
	WriteFormat("    Trying to signal Condition %d \n",36,Condition,1);
	SignalCondition(Condition[0],Lock[0]);
	WriteFormat("    Signal Condition %d should FAIL because this Lock is already deleted \n",75,Condition,1);
	WriteFormat("    Trying to Broadcast Condition %d \n",39,Condition,1);
	BroadcastCondition(Condition[0],Lock[0]);
	WriteFormat("    Broadcast Condition %d should FAIL because this Lock is already deleted \n",78,Condition,1);
	
	ReleaseLock(Lock[0]);
	DestroyLock(Lock[0]);
	WriteFormat("------------test end-----------\n",33,0,0);

	return;
}

/*Test Case 3*/
void test3_main()
{
	int tmp;

	WriteFormat("----------Test Case III--------\n",33,0,0);
	WriteFormat("/*Bullet Proof of Lock       */\n",33,0,0);
	
	WriteFormat("3-1 Create Lock with Wrong Address of Name\n",44,0,0);
	CreateLock(-1,10);
	WriteFormat("    Create Lock should FAIL because this name address is out of virtual address \n",82,0,0);

	WriteFormat("3-2 Create Lock with extrem long name length\n",46,0,0);
	CreateLock("testname",10000000);
	WriteFormat("    Create Lock should FAIL because this name length is too long and exceed virtual address \n",94,0,0);

	WriteFormat("3-3 Acquire and Release Uncreated Lock\n",40,0,0);
	WriteFormat("    Trying to Acquire Lock 100\n",32,0,0);
	AcquireLock(100);
	WriteFormat("    Acquire Lock should FAIL because this Lock doesn't exist \n",63,0,0);
	WriteFormat("    Trying to Release Lock 100\n",32,0,0);
	ReleaseLock(100);
	WriteFormat("    Release Lock should FAIL because this Lock doesn't exist \n",63,0,0);
	
	WriteFormat("3-4 Acquire and Release Lock with unreasonable index\n",60,0,0);
	WriteFormat("    Trying to Acquire Lock -1 \n",32,0,0);
	AcquireLock(-1);
	WriteFormat("    Acquire Lock should FAIL because this index is out of bound \n",66,0,0);
	WriteFormat("    Trying to Release Lock -1 \n",32,0,0);
	ReleaseLock(-1);
	WriteFormat("    Release Lock should FAIL because this index is out of bound \n",66,0,0);
	WriteFormat("    Trying to Acquire Lock 10000\n",34,0,0);
	AcquireLock(10000);
	WriteFormat("    Acquire Lock should FAIL because this index is out of bound \n",66,0,0);
	WriteFormat("    Trying to Release Lock 10000\n",34,0,0);
	ReleaseLock(10000);
	WriteFormat("    Release Lock should FAIL because this index is out of bound \n",66,0,0);
	
	WriteFormat("------------test end-----------\n",33,0,0);

	return;
}

/*Test Case 4*/
void test4_main()
{
	int tmp;

	WriteFormat("----------Test Case IV---------\n",33,0,0);
	WriteFormat("/*Bullet Proof of Condition  */\n",33,0,0);
	
	WriteFormat("4-0 Prepare Locks to be used\n",30,0,0);
	Lock[1]=CreateLock("tempLock",8);
	Condition[1]=CreateCondition("tempCondition",13);
	WriteFormat("    Lock to be used : %d    \n",30,Lock+1,1);
	WriteFormat("    Condition to be used : %d    \n",35,Condition+1,1);
	
	WriteFormat("4-1 Create Condition with Wrong Address of Name\n",49,0,0);
	CreateCondition(-1,10);
	WriteFormat("    Create Condition should FAIL because this name address is out of virtual address \n",87,0,0);

	WriteFormat("4-2 Create Condition with extrem long name length\n",51,0,0);
	CreateCondition("testname",10000000);
	WriteFormat("    Create Condition should FAIL because this name length is too long and exceed virtual address \n",99,0,0);
	
	WriteFormat("4-3 Wait, Signal and Broadcast Uncreated Condition \n",53,0,0);
	tmp = Condition[1]+100;
	WriteFormat("    Trying to Wait Condition %d\n",33,&tmp,1);
	WaitCondition(tmp,Lock[1]);
	WriteFormat("    Trying to Signal Condition %d\n",35,&tmp,1);
	SignalCondition(tmp,Lock[1]);
	WriteFormat("    Trying to Broadcast Condition %d\n",38,&tmp,1);
	BroadcastCondition(tmp,Lock[1]);
	WriteFormat("    These operations should FAIL because this Condition doesn't exist\n",71,0,0);
	

	WriteFormat("4-4 Wait, Signal and Broadcast Condition with Uncreated Lock\n",62,0,0);
	tmp = Lock[1] + 100;
	WriteFormat("    Trying to Wait Condition with Lock %d\n",43,&tmp,1);
	WaitCondition(Condition[1],tmp);
	WriteFormat("    Trying to Signal Condition with Lock %d\n",45,&tmp,1);
	SignalCondition(Condition[1],tmp);
	WriteFormat("    Trying to Broadcast Condition with Lock %d\n",48,&tmp,1);
	BroadcastCondition(Condition[1],tmp);
	WriteFormat("    These operations should FAIL because this Lock doesn't exist\n",66,0,0);
	
	WriteFormat("4-5 Wait, Signal and Broadcast Condition of Unreasonable index\n",60,0,0);
	WriteFormat("    Trying to Wait Condition -1 \n",34,0,0);
	WaitCondition(-1,Lock[1]);
	WriteFormat("    Trying to Signal Condition -1 \n",36,0,0);
	SignalCondition(-1,Lock[1]);
	WriteFormat("    Trying to Broadcast Condition -1 \n",39,0,0);
	BroadcastCondition(-1,Lock[1]);
	WriteFormat("    These operations should FAIL because this index is out of bound \n",70,0,0);
	
	WriteFormat("4-5 Wait, Signal and Broadcast Condition of Unreasonable index\n",60,0,0);
	WriteFormat("    Trying to Wait Condition -1 \n",34,0,0);
	WaitCondition(-1,Lock[1]);
	WriteFormat("    Trying to Signal Condition -1 \n",36,0,0);
	SignalCondition(-1,Lock[1]);
	WriteFormat("    Trying to Broadcast Condition -1 \n",39,0,0);
	BroadcastCondition(-1,Lock[1]);
	WriteFormat("    These operations should FAIL because this index is out of bound \n",70,0,0);
	WriteFormat("    Trying to Wait Condition 10000 \n",37,0,0);
	WaitCondition(10000,Lock[1]);
	WriteFormat("    Trying to Signal Condition 10000 \n",39,0,0);
	SignalCondition(10000,Lock[1]);
	WriteFormat("    Trying to Broadcast Condition 10000 \n",42,0,0);
	BroadcastCondition(10000,Lock[1]);
	WriteFormat("    These operations should FAIL because this index is out of bound \n",70,0,0);
	
	WriteFormat("4-6 Wait, Signal and Broadcast Condition with Lock of Unreasonable index\n",74,0,0);
	WriteFormat("    Trying to Wait Condition with Lock -1 \n",44,0,0);
	WaitCondition(Condition[1],-1);
	WriteFormat("    Trying to Signal Condition with Lock -1 \n",46,0,0);
	SignalCondition(Condition[1],-1);
	WriteFormat("    Trying to Broadcast Condition with Lock -1 \n",49,0,0);
	BroadcastCondition(Condition[1],-1);
	WriteFormat("    These operations should FAIL because this index is out of bound \n",70,0,0);
	WriteFormat("    Trying to Wait Condition with Lock 10000 \n",47,0,0);
	WaitCondition(Condition[1],10000);
	WriteFormat("    Trying to Signal Condition with Lock 10000 \n",49,0,0);
	SignalCondition(Condition[1],10000);
	WriteFormat("    Trying to Broadcast Condition with Lock 10000 \n",52,0,0);
	BroadcastCondition(Condition[1],10000);
	WriteFormat("    These operations should FAIL because this index is out of bound \n",70,0,0);
	
	DestroyLock(Lock[1]);
	DestroyCondition(Condition[1]);
	WriteFormat("------------test end-----------\n",33,0,0);
}
	
/*test case 5*/
void test5_main()
{
	int tmp[2];

	WriteFormat("----------Test Case V----------\n",33,0,0);
	WriteFormat("/*Lock&Condition in multiProcess*/\n",36,0,0);
	
	WriteFormat("Process0: Create Lock & Condition \n",36,0,0);
	Lock[3] = CreateLock("MultiProcessLock1",17);
	Condition[3] = CreateCondition("MultiProcessCond1",17);
	tmp[0] = Lock[3];
	tmp[1] = Condition[3];
	WriteFormat("Process0: Lock Created, handle is %d \n",39,Lock+3,1);
	WriteFormat("Process0: Condition Created, handle is %d \n",44,Condition+3,1);
	WriteFormat("Process0: Exec another process to Operate Lock %d and Condition %d \n",69,tmp,2);
	Exec("../test/testPart1_p2",20);
	for(i=0;i<5;i++)
		Yield();
	WriteFormat("Process0: Another process should fail to Operate Lock %d and Condition %d because they belong to Me (Process 0) \n",113,tmp,2);
	DestroyLock(Lock[3]);
	DestroyCondition(Condition[3]);
	WriteFormat("------------test end-----------\n",33,0,0);
}


int main()
{
	test1_main();	
	test2_main();
	test3_main();
	test4_main();
	test5_main();



/*******************
 *  Functionality  *
 *      Test       *
 *******************/


	/*Lock[0] = CreateLock("TestLock0",9);*/			/*Create Locks and Conditions*/
	/*Lock[1] = CreateLock("TestLock1",9);*/
	/*Lock[2] = CreateLock("TestLock2",9);*/
	/*Condition[0] = CreateCondition("TestCondition1",14);*/
	/*Condition[1] = CreateCondition("TestCondition2",14);*/
	
	/*AcquireLock(Lock[0]);*/	/*Acquire Lock 0*/
	/*ReleaseLock(Lock[1]);*/	/*Should fail, because Lock 1 is not held by the thread*/
	/*ReleaseLock(Lock[0]);*/	/*Release should succeed*/
	/*DestroyLock(Lock[0]);*/	/*Should Succeed*/
	/*AcquireLock(Lock[0]);*/	/*Should Fail because this lock is already deleted*/


/*
	for(i=0;i<3;i++)
		Fork(thread1);
	
	for(i=0;i<5;i++)
		Yield();
*/

/*	WaitCondition(CV,Lock1);*/
	
	/*WaitCondition(Condition[0],Lock[1]);*/			/*Should Fail because this lock is not held by current thread*/
	/*AcquireLock(Lock[2]);*/							/*should Succeed*/
	/*BroadcastCondition(Condition[0],Lock[2]);*/		/*should fail due to no thread is waiting*/
	/*SignalCondition(Condition[0],Lock[2]);*/			/*should fail due to no thread is waiting*/
	

/*******************
 *   BulletProof   *
 *       Test      *
 *******************/
	/*AcquireLock(50000);			*/			/*Acquire Should fail, because this index is invalid*/
	/*DestroyCondition(-1);			*/		/*Release Should fail, because this index is invalid*/
	
	/*AcquireLock(82);				*/		/*Should fail, dut to this Lock is either not exist or possessed by other process*/
	/*WaitCondition(56,Lock[0]);	*/			/*Should fail, dut to this Condition is either not exist or possessed by other process*/
	/*WaitCondition(Condition[0],78);*/			/*Should fail, dut to this Lock is either not exist or possessed by other process*/


	/*DestroyLock(Lock[0]);	*/				/*Destroy Locks and Conditions*/
	/*DestroyLock(Lock[1]);	*/
	/*DestroyLock(Lock[2]);	*/
	/*DestroyCondition(Condition[0]);*/
	/*DestroyCondition(Condition[1]);*/
	
	Exit(0);
}
